<template>
  <vxe-layout-container
      vertical
      style="height: 100vh"
  >
    <vxe-layout-header></vxe-layout-header>
    <vxe-layout-body>
      <vxe-table
          border
          size="mini"
          class="mylist-table"
          :column-config="columnConfig"
          :row-config="rowConfig"
          :export-config="{}"
          :edit-config="editConfig"
          :menu-config="menuConfig"
          ref="tableRef"
          height="100%"
          :virtual-x-config="{enabled: true, gt: 500}"
          :virtual-y-config="{enabled: true, gt: 500}"
          :data="list"
          @menu-click="contextMenuClickEvent"
      >
        <vxe-column type="seq" width="80" v-if="tableColumns.length"></vxe-column>
        <vxe-column
            v-for="(col, index) in tableColumns"
            :key="col.title + index"
            :title="col.title"
            :field="col.field"
            min-width="140"
            :edit-render="{name: 'input'}"
        ></vxe-column>
        <template #empty>
          <div
              style="height: 60vh; display: flex; justify-content: center; align-items: center;"
              @dragenter.prevent="handleDragEnter"
              @dragover.prevent="handleDragOver"
              @dragleave.prevent="handleDragLeave"
              @drop.prevent="handleDrop"
              ref="dropZone"
              class="drop-zone"
              :class="{ 'highlight': isDragging }"
          >
            <p>没有更多数据了！</p>
            <vxe-button content="加载文件" size="mini" @click="loadFile"></vxe-button>
          </div>
        </template>
      </vxe-table>
    </vxe-layout-body>

    <vxe-layout-footer class="footer">
      <vxe-button content="加载文件" size="mini" @click="loadFile"></vxe-button>
      <vxe-button content="查看数据" size="mini" @click="viewData" style="margin-right: 6px"></vxe-button>
      <vxe-toolbar ref="toolbarRef" :buttons="toolbarButtons" size="mini"></vxe-toolbar>
      <vxe-input v-model="filterName" size="mini" type="search" style="margin-left: 6px" placeholder="全表搜索"
                 clearable
                 @change="searchEvent"></vxe-input>
      <div style="flex: 1"></div>
      <vxe-switch v-model="titleStatus" size="small" open-label="展示表头" close-label="关闭表头"
                  :class="{
                      'my-switch-title-on': titleStatus,
                      'my-switch-title-off': !titleStatus,
                  }"
                  @change="titleStatusChange"
      ></vxe-switch>
      <vxe-switch v-model="themeStatus" size="small" open-icon="vxe-icon-sunny" close-icon="vxe-icon-moon"
                  :class="{
                      'my-switch-on': themeStatus,
                      'my-switch-off': !themeStatus,
                  }"
                  @change="themeChange"
      ></vxe-switch>
      <input
          ref="fileInput"
          type="file"
          style="display: none;"
          accept=".csv"
          @change="handleFileChange"
      />

    </vxe-layout-footer>
  </vxe-layout-container>
</template>

<script lang="tsx" setup>
import {ref, onMounted, reactive} from 'vue'
import Papa from 'papaparse'
import {
  VxeTableEvents,
  VxeTableInstance,
  VxeTablePropTypes,
  VxeToolbarInstance,
  VxeToolbarPropTypes
} from 'vxe-table'
import XEUtils from 'xe-utils'
import {VxeUI} from "vxe-pc-ui";
import {invoke} from "@tauri-apps/api/core";
import { open } from '@tauri-apps/plugin-fs';

interface RowVO {
  [key: string]: any;
}
const editConfig = ref<VxeTablePropTypes.EditConfig>({
  trigger: 'dblclick',
  mode: 'cell'
})
const tableData = ref<any[]>([])
const tableColumns = ref<{ [key: string]: any }[]>([])
const filterName = ref('')
const list = ref<RowVO[]>([])
const toolbarRef = ref<VxeToolbarInstance>()
const tableRef = ref<VxeTableInstance<RowVO>>()
const columnConfig = reactive<VxeTablePropTypes.ColumnConfig<RowVO>>({
  resizable: true,
  useKey: true,
  isCurrent: true,
  isHover: true,
  // drag: true
})
const rowConfig = reactive<VxeTablePropTypes.RowConfig<RowVO>>({
  useKey: true,
  isCurrent: true,
  isHover: true
})
const fileInput = ref(null)
let oriFile: File
let oriText: string = ref('')

// ------------------------------ 表头配置 ---------------------------
const titleStatus = ref(!!localStorage.getItem('titleStatus'))
const titleStatusChange = () => {
  localStorage.setItem('titleStatus', titleStatus.value ? '1' : '')
  parseFile(oriFile)
}


// ------------------------------ 主题配置 ---------------------------
const themeStatus = ref(!!localStorage.getItem('theme'))
const themeChange = () => {
  VxeUI.setTheme(themeStatus.value ? 'light' : 'dark')
  localStorage.setItem('theme', themeStatus.value ? '1' : '')
}
themeChange()

const generateTitle = (length: number): string[] => {
  const columns: string[] = []

  for (let i = 0; i < length; i++) {
    let column = ''
    let num = i + 1 // Excel列从1开始计数

    while (num > 0) {
      const remainder = (num - 1) % 26
      column = String.fromCharCode(65 + remainder) + column // 65是'A'的ASCII码
      num = Math.floor((num - 1) / 26)
    }

    columns.push(column)
  }
  return columns
}
// ------------------------------ 文件导入 ---------------------------
const parseFile = (file: File) => {
  VxeUI.loading.open({})
  tableColumns.value = []
  Papa.parse(file, {
    complete: (result: any) => {
      const fields = result.data
      const generateTitles = generateTitle(fields[0]?.length || 0)
      if (titleStatus.value) {
        const titles = fields.shift()
        tableColumns.value = titles.map((field: string, index: number) => ({
          title: field,
          field: generateTitles[index],
        }))
      } else {
        tableColumns.value = generateTitles.map(field => ({
          title: field,
          field: field,
        }))
      }
      tableData.value = fields.map((field: any[]) => {
        const obj: {
          [key: string]: any;
        } = {}
        field.forEach((item, index) => {
          obj[generateTitles[index]] = item
        })
        return obj
      })
      handleSearch()
      setTimeout(() => {
        VxeUI.loading.close()
      }, 300)
    },
    // dynamicTyping: true,    // 自动转换数字、布尔等类型
    error: (error: any) => {
      setTimeout(() => {
        VxeUI.loading.close()
      }, 300)
      VxeUI.modal.message({content: 'CSV 解析错误:', status: error})
    },
    header: false,
    skipEmptyLines: true
  })
}

const handleFileChange = (event: any) => {
  setFile(event.target?.files[0])
}

const setFile = async (file: File) => {
  if (!file) return
  if (!file.type.includes('csv')) {
    VxeUI.modal.message({content: '请导入正确的文件', status: 'warning'})
    return;
  }
  oriFile = file
  oriText.value = await file.text()
  parseFile(oriFile)
}
const loadFile = () => {
  // 拉起浏览器的选择文件框，选择本地文文件
  fileInput.value!.click()
}


// -----------------------文件拖拽

const dropZone = ref(null)
const isDragging = ref(false)
const fileContent = ref('')

// 拖拽进入
const handleDragEnter = (e) => {
  isDragging.value = true
}

// 拖拽悬停（必须阻止默认行为，否则 drop 不触发）
const handleDragOver = (e) => {
  isDragging.value = true
}

// 拖拽离开
const handleDragLeave = (e) => {
  // 只有当鼠标真正离开容器时才取消高亮
  const dragRect = dropZone.value?.getBoundingClientRect()
  if (
      e.clientX < dragRect.left ||
      e.clientX > dragRect.right ||
      e.clientY < dragRect.top ||
      e.clientY > dragRect.bottom
  ) {
    isDragging.value = false
  }
}

// 释放文件（核心逻辑）
const handleDrop = (e) => {
  isDragging.value = false
  const files = e.dataTransfer.files
  if (files.length === 0) return
  const file = files[0]
  setFile(file)
  // console.log('拖入的文件:', file.name, file.type, file.size)
}



// ----------------------- 搜索

const handleSearch = () => {
  const filterVal = String(filterName.value).trim().toLowerCase()
  if (filterVal) {
    // const filterRE = new RegExp(filterVal, 'gi')
    const searchProps = tableColumns.value.map(key => key.field)
    const rest = tableData.value.filter(item => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1))
    list.value = rest.map(row => {
      // 搜索为克隆数据，不会污染源数据
      return XEUtils.clone(row)
    })
  } else {
    list.value = tableData.value
  }
}

// 节流函数,间隔500毫秒触发搜索
const searchEvent = XEUtils.throttle(function () {
  handleSearch()
}, 500, {trailing: true, leading: true})
handleSearch()

const toolbarButtons = ref<VxeToolbarPropTypes.Buttons>([
  {code: 'myToolbarExport', name: '直接导出'},
  {code: 'myToolbarSeniorExport', name: '高级导出'},
  // { code: 'myToolbarClearFilter', name: '清除列筛选' },
  {code: 'myToolbarCustom', name: '个性化列'}
])

// -------------------------- 右键菜单 ------------------------------

const menuConfig = reactive<VxeTablePropTypes.MenuConfig<RowVO>>({
  header: {
    options: [
      [
        {code: 'hideColumn', name: '隐藏列', disabled: false},
        {code: 'showAllColumn', name: '取消所有隐藏列', disabled: false}
      ]
    ]
  },
  body: {
    options: [
      [
        {code: 'copy', name: '复制', prefixConfig: {icon: 'vxe-icon-copy'}, disabled: false},
        // { code: 'insertAt', name: '插入', prefixConfig: { icon: 'vxe-icon-add' }, disabled: false },
        // { code: 'remove', name: '删除', prefixConfig: { icon: 'vxe-icon-close' }, disabled: false },
        {code: 'insertAt', name: '插入行', disabled: false},
        // {code: 'insertAt', name: '插入列', disabled: false},
        {code: 'remove', name: '删除', disabled: false},
        {code: 'save', name: '保存', prefixConfig: {icon: 'vxe-icon-save'}, disabled: false}
      ]
    ]
  },
  visibleMethod({options, column}) {
    const isDisabled = !column
    options.forEach(list => {
      list.forEach(item => {
        item.disabled = isDisabled
      })
    })
    return true
  }
})
const contextMenuClickEvent: VxeTableEvents.MenuClick<RowVO> = ({menu, row, column}) => {
  const $table = tableRef.value
  if ($table) {
    switch (menu.code) {
      case 'hideColumn':
        $table.hideColumn(column)
        break
      case 'showAllColumn':
        $table.resetColumn(true)
        break
      case 'copy':
        if (VxeUI.clipboard.copy(row[column.field])) {
          VxeUI.modal.message({content: '已复制到剪贴板！', status: 'success'})
        }
        break
      case 'insertAt':
        $table.insertAt({}, row || -1).then(({row}) => {
          $table.setEditCell(row, column || 'name')
        })
        break
      case 'remove':
        $table.remove(row)
        break
      case 'save':
        VxeUI.modal.message({content: '请导出', status: 'warning'})
        break
    }
  }
}

// -------------------------- 数据查看 ------------------------------
const viewData = () => {
  VxeUI.modal.open({
    title: `原始文件数据`,
    content: oriText.value || '请导入文件',
    mask: false,
    lockView: false,
    escClosable: true,
    width: 600,
    height: 400,
    showZoom: true
  })
}

// -------------------------- 以tauri打开 ------------------------------
const openTauriFile = async () => {
  invoke('get_startup_image_path').then(async (path) => {
    if (path){
      // https://tauri.org.cn/plugin/file-system/
      const file = await open(path, {
        read: true,
      })
      const stat = await file.stat();
      const buf = new Uint8Array(stat.size);
      await file.read(buf)
      const textContents = new TextDecoder().decode(buf);
      setFile(
          new File([textContents],
          'xx.csv',
          {type: 'csv/plain'})
      )
      await file.close();
    }
  })
}


onMounted(async () => {
  const $table = tableRef.value
  const $toolbar = toolbarRef.value
  if ($table && $toolbar) {
    $table.connect($toolbar)
  }
  await openTauriFile()
})
</script>

<style scoped lang="scss">
.footer {
  border-top: 1px solid #333;
  padding: 0 10px;
  display: flex;
  justify-content: start;
  align-items: center;
  //gap: 4px;
}


::v-deep(.my-switch-on.vxe-switch .vxe-switch--button) {
  background-color: #e5e5e5;
}

::v-deep(.my-switch-off.vxe-switch .vxe-switch--button) {
  background-color: #363636;
}

::v-deep(.my-switch-title-on.vxe-switch .vxe-switch--button) {
  background-color: rgba(54, 236, 52, 0.46);
}

::v-deep(.my-switch-title-off.vxe-switch .vxe-switch--button) {
  background-color: #363636;
}
.drop-zone {
  width: 100%;
  border: 2px dashed #3fa174;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  color: #666;
  transition: all 0.3s;
}

.drop-zone.highlight {
  background-color: #e6fff5;
  border-color: #2a9d8f;
  color: #2a9d8f;
}

.output {
  margin-top: 20px;
  padding: 10px;
  background: #f5f5f5;
  border: 1px solid #ddd;
  border-radius: 4px;
  white-space: pre-wrap;
  word-break: break-all;
}
</style>